import { isEqual, isObjectLike } from 'lodash-es'

// 遍历json
export const traverseJson = (
    json: any,
    cb: (
        key: string,
        value: any,
        json: any,
        keyPath?: string[],
    ) => boolean | void,
    keyPath?: string[],
) => {
    if (!json) {
        return
    }
    Object.keys(json).forEach((key) => {
        const newKeyPath = [...(keyPath || []), key]
        const value = json[key]
        // 原始值
        if (typeof value !== 'object' || value === null) {
            cb(key, value, json, newKeyPath)
            return
        }
        const nextable = cb(key, value, json, newKeyPath)
        if (nextable === false) {
            return
        }
        traverseJson(json[key], cb, newKeyPath)
    })
    return
}

// 深拷贝并执行回调
export const cloneDeepWith = (
    obj: any,
    cb: (
        key: string,
        value: any,
        keyPath: string[],
    ) => {
        newKey: string
        newValue: any
        nextable?: boolean
        ignore?: boolean
    },
    keyPath: string[] = [],
) => {
    if (!isObjectLike(obj)) {
        return obj
    }

    const newObj: any = Array.isArray(obj) ? [] : {}
    Object.keys(obj).forEach((key) => {
        const newKeyPath = [...keyPath, key]
        const value = obj[key]
        const { newKey, newValue, nextable, ignore } = cb(
            key,
            value,
            newKeyPath,
        )
        if (ignore) {
            return
        }
        newObj[newKey] = newValue
        if (nextable === false || !isObjectLike(value)) {
            return
        }
        newObj[newKey] = cloneDeepWith(value, cb, newKeyPath)
    })
    return newObj
}

// 判断value是否包含arr中的任意一个元素
export const includesAny = (value: any, arr: string[]) => {
    return arr.some((item) => value.includes(item))
}

// 判断value是否以arr中的任意一个元素结尾
export const endsWithAny = (value: any, arr: string[]) => {
    return arr.some((item) => value.endsWith(item))
}

// 判断value是否等于arr中的任意一个元素
export const equalsAny = (value: any, arr: string[]) => {
    return arr.some((item) => value === item)
}

// 深度去重
export const deepUniqByValue = (obj: any, processed = new WeakMap()) => {
    // 如果不是对象或数组，直接返回
    if (obj === null || typeof obj !== 'object') {
        return obj
    }

    // 如果已经处理过这个对象，返回处理后的结果（避免循环引用）
    if (processed.has(obj)) {
        return processed.get(obj)
    }

    // 处理数组
    if (Array.isArray(obj)) {
        const result: any[] = []
        processed.set(obj, result)

        for (const item of obj) {
            // 先递归处理每个元素
            const processedItem = deepUniqByValue(item, processed)

            // 使用 _.isEqual 检查是否已存在相同值的元素
            const isDuplicate = result.some((existingItem) =>
                isEqual(existingItem, processedItem),
            )

            if (!isDuplicate) {
                result.push(processedItem)
            }
        }

        return result
    }

    // 处理对象
    const result: any = {}
    processed.set(obj, result)

    for (const [key, value] of Object.entries(obj)) {
        result[key] = deepUniqByValue(value, processed)
    }

    return result
}
